﻿using System;
using System.Collections.Generic;
using System.IO;
using Microsoft.VisualBasic.FileIO;
using System.ComponentModel;
using System.Security.AccessControl;


namespace ToolGab.Cleaner
{
    ///============================================================================================
    /// <summary>
    /// Cleaning functions
    /// </summary>
    ///============================================================================================
    public class CleanerEngine
    {
        #region EventDelegates
        public event EventHandler CleaningCompleted;
        public event CleaningProgressChangedEventHandler CleaningProgressChanged;

        #endregion

        /// <summary>
        /// Process counter
        /// </summary>
        private int m_ProcessCounter;

        /// <summary>
        /// List of current Background counter beeing run
        /// </summary>
        private List<BackgroundWorker> m_bgwList;

        public CleanerEngine()
        {
            m_ProcessCounter = 0;
            m_bgwList = new List<BackgroundWorker>();
        }
        public void Clean(List<DirectoryInfo> lstDI, List<string> lstExt, bool srchSubFolders)
        {
            if (lstDI.Count<=0 && CleaningCompleted != null)
                    CleaningCompleted(this, EventArgs.Empty);
            
                
            
            foreach (DirectoryInfo di in lstDI)
            {
                BackgroundWorker bgw = new BackgroundWorker();

                bgw.WorkerReportsProgress = true;
                bgw.WorkerSupportsCancellation = true;

                bgw.DoWork += new DoWorkEventHandler(bgw_DoWork);
                bgw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bgw_RunWorkerCompleted);
                bgw.ProgressChanged += new ProgressChangedEventHandler(bgw_ProgressChanged);

                bgw.RunWorkerAsync(new CleaningProcessArgs(di, lstExt, srchSubFolders));
                m_bgwList.Add(bgw);
                m_ProcessCounter++;

                //CleanFolderFiles(di, lstExt, srchSubFolders);

            }
        }
        private void bgw_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            if (e.UserState is CleaningProgressChangedEventArgs)
            {
                CleaningProgressChangedEventArgs fsi = (CleaningProgressChangedEventArgs)e.UserState;
                if (CleaningProgressChanged != null)
                {
                    CleaningProgressChanged(fsi);
                }
            }

        }

        private void bgw_DoWork(object sender, DoWorkEventArgs e)
        {
            if (e.Argument is CleaningProcessArgs
                && sender is BackgroundWorker
                && !((BackgroundWorker)sender).CancellationPending)
            {
                CleaningProcessArgs args = (CleaningProcessArgs)e.Argument;
                BackgroundWorker bgw = (BackgroundWorker)sender;
                CleanFolderFiles(args.IOObject, args.ExtList, args.SearchSubFolder, bgw);
            }
        }
        private void bgw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            // throw new NotImplementedException();
            m_ProcessCounter--;
            if (m_ProcessCounter <= 0)
            {
                if (CleaningCompleted != null)
                    CleaningCompleted(this, EventArgs.Empty);
                
            }
            if (sender is BackgroundWorker)
            {
                m_bgwList.Remove((BackgroundWorker)sender);
            }

        }

        private void CleanFolderFiles(DirectoryInfo dir, List<string> lstExt
            , bool srchSubFolders, BackgroundWorker CurrentBGW)
        {
            if (CurrentBGW.CancellationPending)
                return;

            foreach (string ext in lstExt)
            {
                if (CurrentBGW.CancellationPending)
                    return;


                try
                {
                    FileInfo[] fiList = dir.GetFiles("*" + ext);

                    foreach (FileInfo fi in fiList)
                    {
                        if (CurrentBGW.CancellationPending)
                            return;
                        //use this code to move file to recycle bin
                        try
                        {

                            CurrentBGW.ReportProgress(0, new CleaningProgressChangedEventArgs(fi));
                            DeleteFileOrFolder(fi);
                        }
                        catch (Exception)
                        {


                        }
                    }
                }
                catch (Exception)
                { }
                    

            }
            if (srchSubFolders)
            {
                try
                {
                    DirectoryInfo[] diList = dir.GetDirectories();

                    foreach (DirectoryInfo di in diList)
                    {
                        if (CurrentBGW.CancellationPending)
                            return;
                        CleanFolderFiles(di, lstExt, srchSubFolders, CurrentBGW);
                    }
                }
                catch (Exception) { }
            }
        }

        ///----------------------------------------------------------------------------------------
        /// <summary>
        /// Delete a file or folder.
        /// </summary>
        /// <param name="fsi">FileInfo or DirectoryInfo to be deleted</param>
        ///----------------------------------------------------------------------------------------
        public static void DeleteFileOrFolder(FileSystemInfo fsi)
        {
            if (Properties.Settings.Default.UseGarbageBin)
            {
                if (fsi is FileInfo)
                {
                    FileSystem.DeleteFile(fsi.FullName, UIOption.OnlyErrorDialogs, RecycleOption.SendToRecycleBin, UICancelOption.DoNothing);

                }
                if (fsi is DirectoryInfo)
                {
                    FileSystem.DeleteDirectory(fsi.FullName, UIOption.OnlyErrorDialogs, RecycleOption.SendToRecycleBin, UICancelOption.DoNothing);

                }
            }


        }


    };
    ///============================================================================================
    /// <summary>
    /// Event Handler
    /// </summary>
    /// <param name="RISCProgressChanged">Event arguments for the shortcuts class</param>
    ///============================================================================================
    public delegate void CleaningProgressChangedEventHandler
    (CleaningProgressChangedEventArgs CleaningProgressChanged);
    ///============================================================================================
    /// <summary>
    /// Event arguments for the shortcuts class
    /// </summary>
    ///============================================================================================
    public class CleaningProgressChangedEventArgs
    {

        public CleaningProgressChangedEventArgs(FileSystemInfo ShortcutIOObject)
        {
            IOObject = ShortcutIOObject;
        }
        public FileSystemInfo IOObject { get; private set; } // readonly

    }

    class CleaningProcessArgs
    {
        public CleaningProcessArgs(DirectoryInfo di, List<string> lstExt, bool searchSubFolder)
        {
            ExtList = lstExt;
            IOObject = di;
            SearchSubFolder = searchSubFolder;
        }
        public DirectoryInfo IOObject { get; private set; } // readonly
        public List<string> ExtList { get; private set; } // readonly
        public bool SearchSubFolder { get; private set; } // readonly

    }

}

